package com.fm.webrtc.websocket.controller;

import android.util.Log;

import com.fm.webrtc.BuildConfig;
import com.fm.webrtc.websocket.message.callback.CallReceiveMessage;
import com.fm.webrtc.websocket.message.callback.CallWebSocketMessage;
import com.fm.webrtc.websocket.message.Message;
import com.fm.webrtc.websocket.message.MessageType;
import com.fm.webrtc.websocket.message.MessageUtil;
import com.fm.webrtc.websocket.WebSocket;
import com.fm.webrtc.websocket.message.request.AuthorizationResponse;
import com.fm.webrtc.websocket.message.request.Join;
import com.fm.webrtc.websocket.message.response.ConnectWebrtcTransportResponse;
import com.fm.webrtc.websocket.message.response.CreateTransportResponse;
import com.fm.webrtc.websocket.message.response.JoinResponse;
import com.fm.webrtc.websocket.message.response.MemberDestroyResponse;
import com.fm.webrtc.websocket.message.response.NewConsumeResponse;
import com.fm.webrtc.websocket.message.response.PauseConsumeResponse;
import com.fm.webrtc.websocket.message.response.PongResponse;
import com.fm.webrtc.websocket.message.response.ProduceResponse;
import com.fm.webrtc.websocket.message.response.ResumeConsumeResponse;
import com.fm.webrtc.websocket.message.response.StatisticsResponse;
import com.google.gson.JsonObject;

import java.lang.reflect.Field;

/**
 * websocket 消息解析
 */
public class MessageController implements CallWebSocketMessage {

    private final static String TAG = MessageController.class.getSimpleName();

    private WebSocket webSocket;

    private String url = BuildConfig.WS_BASE_URL;

    private String roomId = "fm";

    private String peerId = "";

    private CallReceiveMessage callReceiveMessage;

    public MessageController(CallReceiveMessage callReceiveMessage) {
        this.callReceiveMessage = callReceiveMessage;
        this.webSocket = new WebSocket(this);
        this.webSocket.request(url + roomId);
    }

    public void close(){
        this.webSocket.close();
    }

    @Override
    public void receiveMessage(Message<JsonObject> message) {
        JsonObject data = message.getData();

        if (message.getType().equals(MessageType.authorization)){
            this.callReceiveMessage.authorizationResponse(MessageUtil.jsonToObject(data, AuthorizationResponse.class));
        }

        if (message.getType().equals(MessageType.join)) {
            this.callReceiveMessage.joinResponse(joinResponse(message.getData()));
        }

        if (message.getType().equals(MessageType.createTransport)) {
            this.callReceiveMessage.createTransportResponse(createTransportResponse(data));
        }

        if (message.getType().equals(MessageType.newConsumer)) {
            this.callReceiveMessage.newConsumeResponse(newConsumeResponse(data));
        }

        if (message.getType().equals(MessageType.memberDestroy)) {
            this.callReceiveMessage.memberDestroyResponse(memberDestroyResponse(data));
        }

        if (message.getType().equals(MessageType.pauseConsumer)) {
            this.callReceiveMessage.pauseConsumeResponse(MessageUtil.jsonToObject(data, PauseConsumeResponse.class));
        }

        if (message.getType().equals(MessageType.resumeConsumer)) {
            this.callReceiveMessage.resumeConsumeResponse(MessageUtil.jsonToObject(data, ResumeConsumeResponse.class));
        }

        if (message.getType().equals(MessageType.connectWebRtcTransport)) {
            this.callReceiveMessage.connectWebrtcTransportResponse(MessageUtil.jsonToObject(data, ConnectWebrtcTransportResponse.class));
        }

        if (message.getType().equals(MessageType.producer)){
            this.callReceiveMessage.produce(MessageUtil.jsonToObject(data, ProduceResponse.class));
        }

        if (message.getType().equals(MessageType.pong)) {
            this.callReceiveMessage.pong(MessageUtil.jsonToObject(data, PongResponse.class));
        }

        if (message.getType().equals(MessageType.statistics)) {
            this.callReceiveMessage.statistics(MessageUtil.jsonToObject(data, StatisticsResponse.class));
        }
    }

    @Override
    public void open() {
       // this.join();
    }


    /**
     * 反射设置属性
     */
    private <T> T reflectField(T data, String fieldName, Object value) {
        try {

            Field field = null;
            Class<?> currentClass = data.getClass();
            // 在类及其父类中查找属性
            while (currentClass != null && field == null) {
                try {
                    field = currentClass.getDeclaredField(fieldName);
                } catch (NoSuchFieldException e) {
                    // 属性不在当前类中，继续在父类中查找
                    currentClass = currentClass.getSuperclass();
                }
            }
            if (field != null) {
                field.setAccessible(true);
                field.set(data, value);
            }

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return data;
    }

    /**
     * 发送数据
     *
     * @param type
     * @param data
     * @param <T>
     */
    public <T> void send(String type, T data) {
        reflectField(data, "peerId", this.peerId);
        reflectField(data, "roomId", this.roomId);
        Log.e(TAG, data.toString());
        this.webSocket.send(type, data);
    }

    /**
     * 加入房间
     */
    public void join() {
        this.webSocket.send(MessageType.join, new Join(roomId, peerId));
    }


    /**
     * 处理 join 返回数据
     *
     * @param data
     * @return
     */
    public JoinResponse joinResponse(JsonObject data) {
        JoinResponse joinResponse = MessageUtil.jsonToObject(data, JoinResponse.class);
        roomId = joinResponse.getRoomId();
        peerId = joinResponse.getPeerId();
        return joinResponse;
    }


    /**
     * 创建 transport 返回结果
     *
     * @param data
     * @return
     */
    public CreateTransportResponse createTransportResponse(JsonObject data) {
        return MessageUtil.jsonToObject(data, CreateTransportResponse.class);
    }

    /**
     * 新的消费者
     *
     * @param data
     * @return
     */
    public NewConsumeResponse newConsumeResponse(JsonObject data) {
        return MessageUtil.jsonToObject(data, NewConsumeResponse.class);
    }

    public MemberDestroyResponse memberDestroyResponse(JsonObject data) {
        return MessageUtil.jsonToObject(data, MemberDestroyResponse.class);
    }

}
